﻿using CommHelper;
using CommData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using MySql.Data.MySqlClient;

namespace SHDServer
{
    public class SocketServer
    {
        private Socket m_listenSocket;
        private Thread m_checkTimeOut = null;
        private Thread m_Thread_VoiceBroadcast = null;  //语音广播线程
        private int m_numConnections = GlobalData.NumConnections; //最大支持连接个数
        private VoiceBroadcast m_VoiceBroadcast = null;  //语音广播
        private Queue<Int64> m_printOrderIdPool = new Queue<Int64>();
        private Queue<AsyncSocketUserToken> m_asyncSocketUserTokenPool = new Queue<AsyncSocketUserToken>();
        private List<AsyncSocketUserToken> m_asyncSocketUserTokenList = new List<AsyncSocketUserToken>();

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
            AsyncSocketUserToken userToken;
            for (int i = 0; i < m_numConnections; i++) //按照连接数建立读写对象
            {
                userToken = new AsyncSocketUserToken(this, GlobalData.ReceiveBufferSize);
                userToken.EventCloseSocket += new AsyncSocketUserToken.CloseSocket(userToken_EventCloseSocket);
                m_asyncSocketUserTokenPool.Enqueue(userToken);
            }
        }

        /// <summary>
        /// 开启socket侦听
        /// </summary>
        public void Start()
        {
            if (!IsConnectDatabase())
            {
                ConsoleHelper.WriteLine("Server exited!");
                return;
            }

            Init();

            m_checkTimeOut = new Thread(new ThreadStart(
                  delegate
                  {
                      byte[] sendbytes = new byte[0];
                      while (true)
                      {
                          System.Threading.Thread.Sleep(600000);
                          SendResponseAll(sendbytes);
                      }
                  }
              ));
            m_checkTimeOut.IsBackground = true;
            m_checkTimeOut.Start();

            //语音广播
            m_VoiceBroadcast = new VoiceBroadcast(this);
            m_Thread_VoiceBroadcast = new Thread(new ThreadStart(m_VoiceBroadcast.StartToBroadcaseScanOrder));
            m_Thread_VoiceBroadcast.IsBackground = true;
            m_Thread_VoiceBroadcast.Start();

            IPEndPoint ipend = new System.Net.IPEndPoint(System.Net.IPAddress.Any,
               GlobalData.ListenPort);
            m_listenSocket = new Socket(ipend.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            m_listenSocket.Bind(ipend);

            m_listenSocket.Listen(m_numConnections);
            ConsoleHelper.WriteLine(string.Format("开放的服务器地址为：{0},端口：{1}", ipend.Address, ipend.Port));
            StartAccept(null);
        }

        /// <summary>
        /// 关闭socket、
        ///
        /// </summary>
        public void Stop()
        {
            try
            {
                m_listenSocket.Shutdown(SocketShutdown.Both);
                m_listenSocket.Close();
            }
            catch (Exception e)
            {
                LogHelper.WriteErrorLog(e.Message);
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="acceptEventArgs"></param>
        public void StartAccept(SocketAsyncEventArgs acceptEventArgs)
        {
            if (acceptEventArgs == null)
            {
                acceptEventArgs = new SocketAsyncEventArgs();
                acceptEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
            }
            else
            {
                acceptEventArgs.AcceptSocket = null; //释放上次绑定的Socket，等待下一个Socket连接
            }
            //m_maxNumberAcceptedClients.WaitOne(); //获取信号量
            bool willRaiseEvent = m_listenSocket.AcceptAsync(acceptEventArgs);

            if (!willRaiseEvent)
            {
                ProcessAccept(acceptEventArgs);
            }
        }

        private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs acceptEventArgs)
        {
            try
            {
                ProcessAccept(acceptEventArgs);
            }
            catch (Exception E)
            {
                LogHelper.WriteErrorLog(E.Message);
            }
        }

        private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs)
        {
            try
            {
                if (acceptEventArgs.AcceptSocket != null && acceptEventArgs.AcceptSocket.Connected)
                {
                    AsyncSocketUserToken userToken = null;
                    lock (m_asyncSocketUserTokenList)
                    {
                        userToken = m_asyncSocketUserTokenPool.Dequeue();
                        userToken.ConnectSocket = acceptEventArgs.AcceptSocket;
                        m_asyncSocketUserTokenList.Add(userToken);
                    }
                    //添加到正在连接列表
                    userToken.Receive();
                }
            }
            catch (Exception e)
            {
                LogHelper.WriteErrorLog("链接" + e.Message);
            }
            finally
            {
                StartAccept(acceptEventArgs); //把当前异步事件释放，等待下次连接
            }
        }

        private void userToken_EventCloseSocket(AsyncSocketUserToken asyncSocketUserToken)
        {
            try
            {
                asyncSocketUserToken.ConnectSocket = null;
                lock (m_asyncSocketUserTokenList)
                {
                    m_asyncSocketUserTokenList.Remove(asyncSocketUserToken);
                    m_asyncSocketUserTokenPool.Enqueue(asyncSocketUserToken);
                }
            }
            catch (Exception E)
            {
                LogHelper.WriteErrorLog(E.Message);
            }
        }

        public void SendResponseAll(byte[] buf)
        {
            List<AsyncSocketUserToken> listAsyncSocketUserToken = null;

            lock (m_asyncSocketUserTokenList)
            {
                listAsyncSocketUserToken = new List<AsyncSocketUserToken>(m_asyncSocketUserTokenList);
            }

            foreach (var item in listAsyncSocketUserToken)
            {
                item.SendData(buf);
            }
        }

        /// <summary>
        /// 是否可连接数据库
        /// </summary>
        /// <returns></returns>
        private bool IsConnectDatabase()
        {
            string connectionString = string.Empty;

            try
            {
                connectionString = AppSettingsHelper.GetText("ConnectionString");

                using (MySqlConnection connection = new MySqlConnection(connectionString))
                {
                    connection.Open();
                    connection.Close();
                }

                return true;
            }
            catch (Exception e)
            {
                string log = string.Format("{0}\nPlease check connection string: {1}\n", e.Message, connectionString);
                LogHelper.WriteErrorLog(log);
                ConsoleHelper.Write(log);
            }

            return false;
        }
    }
}